package com.adnaan.backend.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.adnaan.backend.entity.*;
import com.adnaan.backend.entity.dto.OptionDto;
import com.adnaan.backend.entity.vo.ViewHistoryVo;
import com.adnaan.backend.mapper.ArticleMapper;
import com.adnaan.backend.mapper.UserCollectMapper;
import com.adnaan.backend.mapper.UserCommentMapper;
import com.adnaan.backend.mapper.UserLikesMapper;
import com.adnaan.backend.service.ArticleService;
import com.adnaan.backend.service.SysUserService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * author: adnaan
 * create: 2025-02-19 13:09
 * Description:
 */
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Resource
    private SysUserService userService;

    @Resource
    private UserLikesMapper userLikesMapper;

    @Resource
    private UserCollectMapper userCollectMapper;

    @Resource
    private UserCommentMapper userCommentMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public List<OptionDto> getTags(Long id) {
        return baseMapper.getTags(id);
    }

    @Override
    public void deleteTags(Long id) {
        baseMapper.deleteTags(id);
    }

    @Override
    public void insertTags(Long id, List<String> tagIds) {
        baseMapper.insertTags(id, tagIds);
    }

    @Override
    public boolean readHistory(ViewHistoryVo viewHistoryVo) {
        // 判断是否已经存在，如果存在则更新，如果不存在则插入
        viewHistoryVo.setViewTime(new Date());
        viewHistoryVo.setUserId(StpUtil.getLoginIdAsLong());
        if (baseMapper.containsRecord(viewHistoryVo.getArticleId(), viewHistoryVo.getUserId())) {
            return baseMapper.updateHistory(viewHistoryVo);
        }
        return baseMapper.insertHistory(viewHistoryVo);
    }

    @Override
    public void likeArticle(Long userId, Long articleId) {
        if (isArticleLiked(userId, articleId)) {
            cancelLikeArticle(userId, articleId);
            return;
        }
        UserLikes userLikes = new UserLikes();
        userLikes.setUserId(userId);
        userLikes.setArticleId(articleId);
        userLikes.setLikeTime(new Date());
        userLikesMapper.insert(userLikes);
        // 更新 Redis 缓存
        redisTemplate.opsForSet().add("article_likes:" + articleId, userId);
    }

    private void cancelLikeArticle(Long userId, Long articleId) {
        userLikesMapper.deleteLike(userId, articleId);
        // 更新 Redis 缓存
        redisTemplate.opsForSet().remove("article_likes:" + articleId, userId);
    }

    @Override
    public boolean isArticleLiked(Long userId, Long articleId) {
        // 先从 Redis 中获取
        Boolean isLiked = redisTemplate.opsForSet().isMember("article_likes:" + articleId, userId);
        if (isLiked == null) {
            UserLikes userLikes = userLikesMapper.selectByUserIdAndArticleId(userId, articleId);
            isLiked = userLikes != null;
            if (isLiked) {
                redisTemplate.opsForSet().add("article_likes:" + articleId, userId);
            }
        }
        return isLiked;
    }

    @Override
    public void collectArticle(Long userId, Long articleId) {
        if (isArticleCollected(userId, articleId)) {
            cancelCollectArticle(userId, articleId);
            return;
        }
        UserCollect userCollect = new UserCollect();
        userCollect.setUserId(userId);
        userCollect.setArticleId(articleId);
        userCollect.setCollectTime(new Date());
        userCollectMapper.insertCollect(userCollect);
        // 更新 Redis 缓存
        redisTemplate.opsForSet().add("article_collects:" + articleId, userId);
    }

    private void cancelCollectArticle(Long userId, Long articleId) {
        userCollectMapper.deleteCollect(userId, articleId);
        // 更新 Redis 缓存
        redisTemplate.opsForSet().remove("article_collects:" + articleId, userId);
    }

    @Override
    public boolean isArticleCollected(Long userId, Long articleId) {
        // 先从 Redis 中获取
        Boolean isCollected = redisTemplate.opsForSet().isMember("article_collects:" + articleId, userId);
        if (isCollected == null) {
            UserCollect userCollect = userCollectMapper.selectByUserIdAndArticleId(userId, articleId);
            isCollected = userCollect != null;
            if (isCollected) {
                redisTemplate.opsForSet().add("article_collects:" + articleId, userId);
            }
        }
        return isCollected;
    }

    @Override
    public void addComment(Long userId, Long articleId, String commentContent) {
        UserComment userComment = new UserComment();
        userComment.setUserId(userId);
        userComment.setArticleId(articleId);
        userComment.setCommentContent(commentContent);
        userComment.setCommentTime(new Date());
        userCommentMapper.insert(userComment);
    }

    @Override
    public List<UserComment> getCommentsByArticleId(Long articleId) {
        List<UserComment> list = userCommentMapper.selectByArticleId(articleId);
        list.forEach(item -> {
            item.setNickName(userService.getById(item.getUserId()).getNickname());
            item.setAvatar(userService.getById(item.getUserId()).getAvatar());
        });
        return list;
    }

    @Override
    public Integer getLikeCount(Long id) {
        return baseMapper.getLikeCount(id);
    }

    @Override
    public long collectCount(Long userId) {
        return userCollectMapper.collectCount(userId);
    }

    @Override
    public List<UserCollect> collectPage(Page<UserCollect> page, Long userId) {
        long offset = (page.getCurrent() - 1) * page.getSize();
        return userCollectMapper.selectPage(offset, page.getSize(), userId);
    }

    @Override
    public Map<String, String> getContent(Long articleId) {
        return baseMapper.getContent(articleId);
    }

    @Override
    public Map<String, Long> statistics(Long userId) {
        Map<String, Long> map = new HashMap<>();
        map.put("collectCount", collectCount(userId));
        map.put("viewCount", baseMapper.viewCount(userId));
        map.put("recognitionCount", baseMapper.recognitionCount(userId));
        return map;
    }

    @Override
    public long viewHistoryCount(Long userId) {
        return userCollectMapper.viewHistoryCount(userId);
    }

    @Override
    public List<ViewHistory> viewHistoryPage(Page<ViewHistory> page, Long userId) {
        long offset = (page.getCurrent() - 1) * page.getSize();
        return userCollectMapper.viewHistoryPage(offset, page.getSize(), userId);
    }

    @Override
    public boolean clearViewHistory(Long userId) {
        return baseMapper.clearViewHistory(userId);
    }

    @Override
    public void increasePageView(Long id) {
        baseMapper.increasePageView(id);
    }

    @Override
    public List<Long> getArticleIdsByTagIds(String tagIds) {
        List<Integer> list = Arrays.stream(tagIds.split(","))
                .map(Integer::parseInt)
                .collect(Collectors.toList());
        return baseMapper.getArticleIdsByTagIds(list);
    }

    @Override
    public Integer getCollectCount(Long articleId) {
        return userCollectMapper.getCollectCount(articleId);
    }

    @Override
    public Integer getProcess(Long id) {
        return baseMapper.getProcess(StpUtil.getLoginIdAsLong(), id);
    }
}
